using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.Text;
using System.Xml;
using BlogML;
using BlogML.Xml;

namespace Blog.Importer
{
  public class BlogML20Reader : BaseReader
  {
    #region Constructors
    public BlogML20Reader() : base()
    {

    }
    #endregion

    #region Locals & Properties
    
    XmlReader _xmlreader;
    StringDictionary categoryLookup, authorLookup;

    public XmlReader XmlReader
    {
      set { _xmlreader = value; }
    }

    #endregion

    #region Public Methods
    public override void Import()
    {
      BlogMLBlog blog = new BlogMLBlog();

      try
      {
        blog = BlogMLSerializer.Deserialize(_xmlreader);
      }
      catch (Exception ex)
      {
        throw new Exception("BlogML could not load with 2.0 specs.", ex);
      }

      // Setup Web Service Connection
      WebImporter.BlogImporter blogService = CreateWebServiceConnection();

      // Load Categories in StringDictionary
      categoryLookup = new StringDictionary();
      foreach (BlogMLCategory cat in blog.Categories)
      {
        categoryLookup.Add(cat.ID, cat.Title);
      }

      // Load Authors in StringDictionary
      authorLookup = new StringDictionary();
      foreach (BlogMLAuthor author in blog.Authors)
      {
        authorLookup.Add(author.ID, author.Title);
      }

      // Load Posts & Pages (Categories are processed with Posts)
      foreach (BlogMLPost post in blog.Posts)
      {
        int triesLeft = 2;
        while (triesLeft > 0)
        {
          try
          {
            // Load through WebService
            if (post.PostType == BlogPostTypes.Normal)
              LoadBlogPost(blogService, post);
            else
              LoadBlogPage(blogService, post);

            // Completed without exception
            triesLeft = 0;
          }
          catch (System.Net.WebException)
          {
            // If WebException, try it again once
            System.Threading.Thread.Sleep(5000);
            blogService = CreateWebServiceConnection();
            triesLeft -= 1;
          }
          catch (Exception ex)
          {
            // Different Error
            triesLeft = 0;
            //TODO: Should we keep going? Not for now
            throw ex;
          }
        }

      }

      // When done, force blog to reload posts.
      blogService.ForceReload();

    }

    public override bool Validate()
    {
      BlogMLBlog blog = new BlogMLBlog();
      bool response = true;

      try
      {
        blog = BlogMLSerializer.Deserialize(_xmlreader);
      }
      catch
      {
        response = false;
      }

      return response;
    }

    #endregion

    #region Private Methods

    private WebImporter.BlogImporter CreateWebServiceConnection()
    {
      WebImporter.BlogImporter blogService;
      try
      {
        blogService = BlogWriter.GetService(_blogPath, _userName, _password);
      }
      catch (Exception ex)
      {
        throw new Exception("BlogEngine Web Service Connection Failed.", ex);
      }

      return blogService;
    }

    private void LoadBlogPost(WebImporter.BlogImporter blog, BlogMLPost post)
    {
      WebImporter.ImportPost import = new WebImporter.ImportPost();
      import.Title = post.Title;
      if (_author == "")
        import.Author = authorLookup[post.Authors[0].Ref]; // Always use first author
      else
        import.Author = _author;
      import.PostDate = post.DateCreated;
      import.Content = BlogWriter.FilterContent(post.Content.UncodedText, blog, _blogPath, _fileOption, _filePath); 
      import.Description = post.Excerpt.UncodedText;
      import.Publish = true; //post.Approved; 

      // Categories
      List<string> categories = new List<string>();
      if (post.Categories.Count > 0)
      {
        for (int i = 0; i < post.Categories.Count; i++)
        {
          categories.Add(categoryLookup[post.Categories[i].Ref]);
        }
      }
      import.Categories = categories.ToArray();

      // Tags not included :(

      // Save Post
      string postID = blog.AddPost(import, post.PostUrl, _removeDups);

      // Save Comments
      foreach (BlogMLComment comment in post.Comments)
      {
        if (_approvedCommentsOnly)
        {
          if (comment.Approved)
            blog.AddComment(postID, comment.UserName, comment.UserEMail, comment.UserUrl, comment.Content.UncodedText, comment.DateCreated);
        }
        else
          blog.AddComment(postID, comment.UserName, comment.UserEMail, comment.UserUrl, comment.Content.UncodedText, comment.DateCreated);
      }

      //TODO: Save Trackbacks



    }

    private void LoadBlogPage(WebImporter.BlogImporter blog, BlogMLPost post)
    {
      //TODO: Load Pages?
      
      // Nothing to test with yet

    }

    #endregion


  }
}
